#include <bits/stdc++.h>
using namespace std ;

const int maxn = 1e5 + 5 ;
int n, m, L, V, p[maxn] ;
struct car {
		int d, v, a ;
		int ne = 0, se = 0 ; // the northest and the southest that over the velocity
} Car[maxn] ;
	
inline void tp1(int neL) {
	int acar = 0, mclose = 0 ;
	for (int i = 1; i <= n; ++ i)
		if (Car[i].v > V && Car[i].d <= neL) acar ++ ;
	if (acar != 0) mclose = m - 1 ;
	else mclose = m ;
	printf("%d %d\n", acar, mclose) ;
}	// 20 pts

inline void tp2(int neL) {
	int acar = 0, mclose = 0 ;
	for (int i = 1; i <= n; ++ i)
		if ((Car[i].v > V && Car[i].se <= neL) || Car[i].se < neL) acar ++ ;
	if (acar != 0) mclose = m - 1 ;
	else mclose = m ;
	printf("%d %d\n", acar, mclose) ;
}	// 20 pts

inline void solve() {
	
	scanf("%d%d%d%d", &n, &m, &L, &V) ;
	bool flagtp1 = true ; // a is always zero
	bool flagtp2 = true ; // a is always over zero
	
	for (int i = 1; i <= n; ++ i) {
		
		scanf("%d%d%d", &Car[i].d, &Car[i].v, &Car[i].a) ;
		
		if (Car[i].a != 0) flagtp1 = false ;
		if (Car[i].a < 0) flagtp2 = false ;
		
		if (Car[i].a > 0) {
			Car[i].ne = L ;
			if (Car[i].v > V) Car[i].se = Car[i].d ;
			else  Car[i].se = Car[i].d + (V * V - Car[i].v * Car[i].v) / (2 * Car[i].a) ;
		}
		
		if (Car[i].a == 0) Car[i].se = Car[i].d, Car[i].ne = L ;
		
		if (Car[i].a < 0) {
			if (Car[i].v > V) {
				Car[i].se = Car[i].d ;
				Car[i].ne = Car[i].d + (V * V - Car[i].v * Car[i].v) / (2 * Car[i].a) ;
			}
		}
		
	}
	
	int pne = 0, pse = L ;
	
	for (int i = 1; i <= m; ++ i) {
		scanf("%d", &p[i]) ;
		pne = max(p[i], pne) ;
		pse = min(p[i], pse) ;
	}
	
	if (flagtp1 == true) { tp1(pne) ; return ; }
	if (flagtp2 == true) { tp2(pne) ; return ; }
}

int main() {

    freopen("detect.in", "r", stdin) ;
    freopen("detect.out", "w", stdout) ;
	
	int T ; scanf("%d", &T) ;
	for (int i = 1; i <= T; ++ i)
		solve() ;
	
    return 0 ;
}	// 40 pts
